﻿-- Author      : Kurapica

--[[
	Advance Frame for DropDownList
--]]
do
	IGAS:NewAddon("IGAS_Studio")
	local _Widget = IGAS.GUI.Widget.DropDownList
	local _WidgetButton = IGAS.GUI.Widget.DropDownList.DropDownMenuButton

	-- From
	local form = CreateFrame(Widget.AdvanceForm, "IGAS_Studio_Advance_DropDownList", coreF)
	form.Caption = L["Advance for DropDownList"]
	form.btnUp.Enabled = true
	form.btnDown.Enabled = true
	form.btnCancel.Visible = false

	local lst = form.List
	local dtg = form.DataGrid
	local _Frame
	
	local _PropList = {
		"Text",
		"TextColor",
		"Icon",
		"IsColorPicker",
		"IsCheckButton",
		"Checked",
		"Enabled",
	}

	dtg.RowCount = 7
	dtg.Cells(1, 1).Text = "Text"
	dtg.Cells(2, 1).Text = "TextColor"
	dtg.Cells(3, 1).Text = "Icon"
	dtg.Cells(4, 1).Text = "IsColorPicker"
	dtg.Cells(5, 1).Text = "IsCheckButton"
	dtg.Cells(6, 1).Text = "Checked"
	dtg.Cells(7, 1).Text = "Enabled"

	dtg.Columns(2).CellType = "Label"
	dtg.Cells(1, 2).CellType = "String"
	dtg.Cells(2, 2).CellType = "Advance"
	dtg.Cells(3, 2).CellType = "String"
	dtg.Cells(4, 2).CellType = "Boolean"
	dtg.Cells(5, 2).CellType = "Boolean"
	dtg.Cells(6, 2).CellType = "Boolean"
	dtg.Cells(7, 2).CellType = "Boolean"

	dtg.Cells(2, 2).Text = "(Advance)"

	-- Scripts
	local function InitMenu(menu, level)
		local info
		local list = {}

		level = level or 0

		for name, mnuBtn in pairs(menu:GetChilds()) do
			if mnuBtn:IsObjectType(_WidgetButton) then
				list[mnuBtn.Index] = mnuBtn
			end
		end

		for _, mnuBtn in ipairs(list) do
			local name =  mnuBtn.Name
			info = {
				Level = level,
				Name = name,
				Button = mnuBtn,
				Menu = menu,
			}

			for i = 1, level do
				name = "  "..name
			end

			lst:AddItem(info, name)

			if mnuBtn.DropDownList then
				InitMenu(mnuBtn.DropDownList, level + 1)
			end
		end

		wipe(list)
	end

	function lst:OnItemChoosed(info)
		dtg.Info = nil

		if not info then
			dtg.RowCount = 7
			dtg.Cells(1, 2).Text = ""
			dtg.Cells(3, 2).Text = ""
			dtg.Cells(4, 2).Text = ""
			dtg.Cells(5, 2).Text = ""
			dtg.Cells(6, 2).Text = ""
			dtg.Cells(7, 2).Text = ""
			return
		end

		dtg.Cells(1, 2).Value = info.Button.Text
		dtg.Cells(3, 2).Value = info.Button.Icon or ""
		dtg.Cells(4, 2).Value = info.Button.IsColorPicker
		dtg.Cells(5, 2).Value = info.Button.IsCheckButton
		dtg.Cells(6, 2).Value = info.Button.Checked
		dtg.Cells(7, 2).Value = info.Button.Enabled

		if info.Button.DropDownList then
			-- DropDownList.MultiSelect
			dtg.RowCount = 8
			dtg.Cells(8, 1).Text = "MultiSelect"
			dtg.Cells(8, 2).CellType = "Boolean"

			dtg.Cells(8, 2).Value = info.Button.DropDownList.MultiSelect
		else
			dtg.RowCount = 7
		end

		dtg.Info = info
	end

	function dtg:OnCellValueChanged(row, column, value)
		if not self.Info or column ~= 2 then
			return
		end

		if row == 1 then
			-- Text
			self.Info.Button.Text = dtg.Cells(row, column).Value or self.Info.Button.Name
		elseif row == 3 then
			-- Icon
			if strtrim(dtg.Cells(row, column).Value) ~= "" then
				self.Info.Button.Icon = strtrim(dtg.Cells(row, column).Value)
			else
				self.Info.Button.Icon = nil
			end
		elseif row == 4 then
			-- IsColorPicker
			self.Info.Button.IsColorPicker = dtg.Cells(row, column).Value
		elseif row == 5 then
			-- IsCheckButton
			self.Info.Button.IsCheckButton = dtg.Cells(row, column).Value
		elseif row == 6 then
			-- Checked
			self.Info.Button.Checked = dtg.Cells(row, column).Value
		elseif row == 7 then
			-- Enabled
			self.Info.Button.Enabled = dtg.Cells(row, column).Value
		elseif row == 8 then
			-- MultiSelect
			self.Info.Button.DropDownList.MultiSelect = dtg.Cells(row, column).Value
		end
	end

	-- TextColor
	local _ColorBtn
	local _ColorProp
	local function _Cb_Color(red, green, blue, alpha)
		local color = {
			red = red,
			green = green,
			blue = blue,
			alpha = alpha,
		}
		_ColorBtn[_ColorProp] = color
	end

	function dtg:OnAdvance(row, column)
		if self.Info and column == 2 then
			_ColorBtn = self.Info.Button
			if row == 2 then
				-- TextColor
				local color = self.Info.Button["TextColor"] or {}
				_ColorProp = "TextColor"
				return IGAS:ColorPick(_Cb_Color, color.red, color.green, color.blue, color.alpha)
			end
		end
	end

	local function addMenuButton(name)
		if name and strtrim(name) ~= "" then
			name = strtrim(name)

			for _, info in ipairs(lst.Keys) do
				if info.Name == name then
					return
				end
			end

			local index = lst:GetSelectedItemIndex()
			
			lst.SelectedIndex = nil

			if index == 0 then 
				index = #lst.Keys
			end

			local info = lst.Keys[index]

			local menu = (info and info.Menu) or _Frame

			local mnuBtn = menu:AddMenuButton(name)
			mnuBtn.Index = ((info and info.Button.Index) or 0) + 1

			local new = {
				Level = (info and info.Level) or 0,
				Name = name,
				Button = mnuBtn,
				Menu = menu,
			}

			for i = 1, new.Level do
				name = "  "..name
			end
			
			lst:InsertItem(index + 1, new, name)
		end
	end

	function form:OnAddClick()
		return IGAS:MsgBox(L["Please input the name of the menu button"], "ic", addMenuButton)
	end

	local function RemoveItem(flag)
		if not flag then
			return
		end

		local parentIndex
		
		if lst:GetSelectedItemIndex() > 0 then
			local index = lst:GetSelectedItemIndex()
			local info = lst:GetItemByIndex(index)
			
			lst.SelectedIndex = nil

			for i = index - 1, 1, -1 do
				if lst.Keys[i].Level == info.Level - 1 then
					parentIndex = i
					break
				end
			end
			
			local subIndex = index

			for i = index + 1, #lst.Keys do
				if lst.Keys[i].Level > info.Level then
					subIndex = i
				else
					break
				end
			end

			for i = subIndex, index, -1 do
				lst.Keys[i].Button:Dispose()

				lst:RemoveItemByIndex(i)
			end
			
			if parentIndex and lst.Keys[parentIndex].Button.DropDownList and lst.Keys[parentIndex].Button.DropDownList.ItemCount == 0 then
				lst.Keys[parentIndex].Button.DropDownList:Dispose()
				lst.Keys[parentIndex].Button.DropDownList = nil
			end
		end
	end

	function form:OnRemoveClick()
		if lst:GetSelectedItemIndex() > 0 then
			return IGAS:MsgBox(L["This operation would remove the menu item and it's sub item"], "c", RemoveItem)
		end
	end

	function form:OnOkayClick()
		self:FireEvent("IGAS_STUDIO_FRAME_ADVANCED", _Frame)
		
		self.Visible = false


		lst:Clear()
	end

	function form:OnUpClick()
		local index = lst:GetSelectedItemIndex()
		local brotherIndex
		local newButton
		local level

		if index > 1 and lst.Keys[index].Level > 0 then
			lst.SelectedIndex = nil
			level = lst.Keys[index].Level

			for i = index -1, 1, -1 do
				if lst.Keys[i].Level == level - 1 then
					brotherIndex = i
					break
				end
			end

			newButton = lst.Keys[brotherIndex].Menu:AddMenuButton(lst.Keys[index].Name)
			newButton.Index = lst.Keys[brotherIndex].Button.Index + 1

			if lst.Keys[index].Button.DropDownList then
				newButton.DropDownList = lst.Keys[index].Button.DropDownList
				newButton.DropDownList.Parent = newButton
				lst.Keys[index].Button.DropDownList = nil
			end

			newButton.Text = lst.Keys[index].Button.Text
			newButton.IsCheckButton = lst.Keys[index].Button.IsCheckButton
			newButton.Checked = lst.Keys[index].Button.Checked
			newButton.IsColorPicker = lst.Keys[index].Button.IsColorPicker
			newButton.Icon = lst.Keys[index].Button.Icon
			newButton.TextColor = lst.Keys[index].Button.TextColor
			newButton.Enabled = lst.Keys[index].Button.Enabled

			lst.Keys[index].Button:Dispose()
			lst.Keys[index].Button = newButton
			lst.Keys[index].Menu = lst.Keys[brotherIndex].Menu

			for i = index, #lst.Keys do
				if i == index or lst.Keys[i].Level > level then
					-- Mean these are sub menu item of this menu item.
					lst.Keys[i].Level = lst.Keys[i].Level - 1

					local name = lst.Keys[i].Name

					for i = 1, lst.Keys[i].Level do
						name = "  "..name
					end

					lst:SetItem(lst.Keys[i], name)
				else
					break
				end
			end			
			
			if brotherIndex and lst.Keys[brotherIndex].Button.DropDownList and lst.Keys[brotherIndex].Button.DropDownList.ItemCount == 0 then
				lst.Keys[brotherIndex].Button.DropDownList:Dispose()
				lst.Keys[brotherIndex].Button.DropDownList = nil
			end
		end
	end

	function form:OnDownClick()
		local index = lst:GetSelectedItemIndex()
		local brotherIndex
		local newButton
		local level

		if index > 1 and lst.Keys[index].Level <= lst.Keys[index - 1].Level then
			lst.SelectedIndex = nil
			level = lst.Keys[index].Level

			for i = index -1, 1, -1 do
				if lst.Keys[i].Level == level then
					break
				elseif lst.Keys[i].Level == level + 1 then
					brotherIndex = i
					break
				end
			end

			if brotherIndex then
				newButton = lst.Keys[brotherIndex].Menu:AddMenuButton(lst.Keys[index].Name)
				newButton.Index = lst.Keys[brotherIndex].Button.Index + 1
			else
				newButton = lst.Keys[index-1].Button:AddMenuButton(lst.Keys[index].Name)
			end

			if lst.Keys[index].Button.DropDownList then
				newButton.DropDownList = lst.Keys[index].Button.DropDownList
				newButton.DropDownList.Parent = newButton
				lst.Keys[index].Button.DropDownList = nil
			end

			newButton.Text = lst.Keys[index].Button.Text
			newButton.IsCheckButton = lst.Keys[index].Button.IsCheckButton
			newButton.Checked = lst.Keys[index].Button.Checked
			newButton.IsColorPicker = lst.Keys[index].Button.IsColorPicker
			newButton.Icon = lst.Keys[index].Button.Icon
			newButton.TextColor = lst.Keys[index].Button.TextColor
			newButton.Enabled = lst.Keys[index].Button.Enabled

			lst.Keys[index].Button:Dispose()
			lst.Keys[index].Button = newButton
			if brotherIndex then
				lst.Keys[index].Menu = lst.Keys[brotherIndex].Menu
			else
				lst.Keys[index].Menu = lst.Keys[index-1].Button.DropDownList
			end

			for i = index, #lst.Keys do
				if i == index or lst.Keys[i].Level > level then
					-- Mean these are sub menu item of this menu item.
					lst.Keys[i].Level = lst.Keys[i].Level + 1

					local name = lst.Keys[i].Name

					for i = 1, lst.Keys[i].Level do
						name = "  "..name
					end

					lst:SetItem(lst.Keys[i], name)
				else
					break
				end
			end
		end
	end

	local function OnHide(self)
		self.Visible = true
		self:ClearAllPoints()
		self:SetPoint("TOPLEFT", form, "TOPRIGHT")
		return true
	end
	
	function form:OnHide()
		if _Frame then
			_Frame:UnStackScript("OnHide", OnHide)
			_Frame:ClearAllPoints()
			_Frame:Hide()
		end
		_ColorBtn = nil
		_ColorProp = nil
		_Frame = nil
	end
	
	function form.btnCancel:OnClick()
		if _Frame then
			_Frame:StackScript("OnHide", OnHide)
			_Frame.Visible = true
			_Frame:ClearAllPoints()
			_Frame:SetPoint("TOPLEFT", form, "TOPRIGHT")
		end
	end

	-- start advance setting for the frame
	function form:SetFrame(frame)
		local text

		-- Clear
		lst:Clear()
		_Frame = frame

		InitMenu(frame)

		frame.Visible = true
		frame:StackScript("OnHide", OnHide)
		frame:ClearAllPoints()
		frame:SetPoint("TOPLEFT", form, "TOPRIGHT")
	end

	-- return the frame's special build-code.Just return the containers.Others would be generated automatically
	local function GetNameList(...)
		local str = ""

		for i = 1, select("#", ...) do
			str = str..Format(select(i, ...))..", "
		end

		return str
	end

	local function SerializeMnuBtn(self, codeList, name, ...)
		-- serialize self
		local nameBtn = name.."_"..self.Name

		tinsert(codeList, ""..nameBtn.." = "..name..":AddMenuButton("..GetNameList(...)..Format(self.Name)..")")
		
		for _, propName in ipairs(_PropList) do
			local str = SerializeProperty(self, propName, nameBtn)
			if str and str ~= "" then
				tinsert(codeList, str)
			end
		end

		-- serialize dropdownlist
		if self.DropDownList and self.DropDownList:IsObjectType(_Widget) then
			local list = {}
			local subName = {...}
			tinsert(subName, self.Name)

			for _, mnuBtn in pairs(self.DropDownList:GetChilds()) do
				if mnuBtn:IsObjectType(_WidgetButton) then
					list[mnuBtn.Index] = mnuBtn
				end
			end

			for _, mnuBtn in ipairs(list) do
				SerializeMnuBtn(mnuBtn, codeList, name, unpack(subName))
			end

			-- MultiSelect
			if next(list) then
				tinsert(codeList, "")
				tinsert(codeList, ""..nameBtn..".DropDownList.MultiSelect = "..Format(self.DropDownList.MultiSelect))
				tinsert(codeList, "")
			end
		end
	end

	function form:Serialize(frame, name, _FrameInfoList)
		local codeList = {}

		if frame and frame:IsObjectType(_Widget) then
			local list = {}

			for _, mnuBtn in pairs(frame:GetChilds()) do
				if mnuBtn:IsObjectType(_WidgetButton) then
					list[mnuBtn.Index] = mnuBtn
				end
			end

			for _, mnuBtn in ipairs(list) do
				SerializeMnuBtn(mnuBtn, codeList, name)
			end
		end

		return table.concat(codeList, "\n")
	end
	
	-- Register
	Advance[_Widget] = form
end